package com.anlu.base.jdk.jdk8;

import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Java 8 函数式接口使用示例
 * 展示各种函数式接口的用法，包括 Function, BiFunction, Consumer, Supplier 等
 */
public class JavaFunctionalInterfacesDemo {

    /**
     * Function接口示例
     * Function<T,R> 接受一个T类型参数，返回一个R类型结果
     */
    @Test
    public void functionDemo() {
        // 基本Function使用
        Function<String, Integer> stringToLength = str -> str.length();
        System.out.println("字符串 'Hello' 的长度: " + stringToLength.apply("Hello"));

        // Function组合 - andThen
        Function<Integer, Integer> multiplyBy2 = x -> x * 2;
        Function<Integer, Integer> add10 = x -> x + 10;
        Function<Integer, Integer> multiplyThenAdd = multiplyBy2.andThen(add10);
        System.out.println("先乘以2再加10: " + multiplyThenAdd.apply(5)); // (5*2)+10 = 20

        // Function组合 - compose
        Function<Integer, Integer> addThenMultiply = multiplyBy2.compose(add10);
        System.out.println("先加10再乘以2: " + addThenMultiply.apply(5)); // (5+10)*2 = 30

        // Function.identity() 示例
        Function<String, String> identity = Function.identity();
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        List<String> sameNames = names.stream().map(identity).collect(Collectors.toList());
        System.out.println("原始列表: " + names);
        System.out.println("使用identity函数: " + sameNames);
    }

    /**
     * BiFunction接口示例
     * BiFunction<T,U,R> 接受T和U类型参数，返回R类型结果
     */
    @Test
    public void biFunctionDemo() {
        // 基本BiFunction使用
        BiFunction<Integer, Integer, Double> powerFunction = (base, exponent) -> Math.pow(base, exponent);
        System.out.println("2的3次方: " + powerFunction.apply(2, 3));

        // BiFunction与Function组合
        BiFunction<Integer, Integer, Integer> multiply = (a, b) -> a * b;
        Function<Integer, String> toString = result -> "结果是: " + result;
        System.out.println(multiply.andThen(toString).apply(3, 4));

        // 在集合操作中使用BiFunction
        Map<String, Integer> map1 = new HashMap<>();
        map1.put("A", 1);
        map1.put("B", 2);

        Map<String, Integer> map2 = new HashMap<>();
        map2.put("B", 3);
        map2.put("C", 4);

        // 合并两个Map，对于重复的key，使用BiFunction定义合并规则
        map1.forEach((key, value) -> map2.merge(key, value, (v1, v2) -> v1 + v2));
        System.out.println("合并后的Map: " + map2);
    }

    /**
     * Consumer接口示例
     * Consumer<T> 接受一个T类型参数，无返回值
     */
    @Test
    public void consumerDemo() {
        // 基本Consumer使用
        Consumer<String> printConsumer = str -> System.out.println("消费内容: " + str);
        printConsumer.accept("Hello World");

        // Consumer组合 - andThen
        Consumer<String> upperCaseConsumer = str -> System.out.println("大写: " + str.toUpperCase());
        Consumer<String> lowerCaseConsumer = str -> System.out.println("小写: " + str.toLowerCase());

        System.out.println("使用andThen组合Consumer:");
        upperCaseConsumer.andThen(lowerCaseConsumer).accept("Hello");

        // 在集合操作中使用Consumer
        List<String> languages = Arrays.asList("Java", "Python", "C++");
        System.out.println("编程语言列表:");
        languages.forEach(printConsumer);
    }

    /**
     * Supplier接口示例
     * Supplier<T> 无参数，返回T类型结果
     */
    @Test
    public void supplierDemo() {
        // 基本Supplier使用
        Supplier<String> helloSupplier = () -> "Hello, World!";
        System.out.println(helloSupplier.get());

        // Supplier生成随机数
        Supplier<Integer> randomSupplier = () -> new Random().nextInt(100);
        System.out.println("随机数1: " + randomSupplier.get());
        System.out.println("随机数2: " + randomSupplier.get());

        // 在orElse中使用Supplier
        Optional<String> emptyOptional = Optional.empty();
        String result = emptyOptional.orElseGet(() -> "默认值");
        System.out.println("Optional中的orElseGet: " + result);

        // 使用Supplier创建集合
        Supplier<List<String>> listSupplier = ArrayList::new;
        List<String> list = listSupplier.get();
        list.add("元素1");
        list.add("元素2");
        System.out.println("使用Supplier创建的列表: " + list);
    }

    /**
     * Predicate接口示例
     * Predicate<T> 接受一个T类型参数，返回boolean值
     */
    @Test
    public void predicateDemo() {
        // 基本Predicate使用
        Predicate<Integer> isEven = num -> num % 2 == 0;
        System.out.println("4是偶数吗? " + isEven.test(4));
        System.out.println("5是偶数吗? " + isEven.test(5));

        // Predicate组合
        Predicate<Integer> isPositive = num -> num > 0;
        Predicate<Integer> isEvenAndPositive = isEven.and(isPositive);
        System.out.println("4是正偶数吗? " + isEvenAndPositive.test(4));
        System.out.println("-2是正偶数吗? " + isEvenAndPositive.test(-2));

        // Predicate.negate
        Predicate<Integer> isOdd = isEven.negate();
        System.out.println("3是奇数吗? " + isOdd.test(3));

        // 在集合过滤中使用Predicate
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        List<Integer> evenNumbers = numbers.stream()
                .filter(isEven)
                .collect(Collectors.toList());
        System.out.println("原始数字: " + numbers);
        System.out.println("偶数: " + evenNumbers);
    }

    /**
     * UnaryOperator接口示例
     * UnaryOperator<T> 接受一个T类型参数，返回T类型结果（T->T）
     */
    @Test
    public void unaryOperatorDemo() {
        // UnaryOperator是Function的特例，参数和返回值类型相同
        UnaryOperator<String> toUpperCase = String::toUpperCase;
        System.out.println("转换为大写: " + toUpperCase.apply("hello"));

        // 在集合操作中使用UnaryOperator
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> doubledNumbers = numbers.stream()
                .map((UnaryOperator<Integer>) num -> num * 2)
                .collect(Collectors.toList());
        System.out.println("原始数字: " + numbers);
        System.out.println("翻倍后: " + doubledNumbers);
    }

    /**
     * BinaryOperator接口示例
     * BinaryOperator<T> 接受两个T类型参数，返回T类型结果（(T,T)->T）
     */
    @Test
    public void binaryOperatorDemo() {
        // BinaryOperator是BiFunction的特例，参数和返回值类型相同
        BinaryOperator<Integer> maxOperator = Math::max;
        System.out.println("最大值: " + maxOperator.apply(10, 20));

        BinaryOperator<String> concatOperator = String::concat;
        System.out.println("字符串连接: " + concatOperator.apply("Hello", "World"));

        // 在reduce操作中使用BinaryOperator
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        Optional<Integer> sum = numbers.stream().reduce(Integer::sum);
        System.out.println("数字列表: " + numbers);
        System.out.println("求和结果: " + sum.orElse(0));

        // 使用minBy和maxBy方法
        BinaryOperator<Integer> minOperator = BinaryOperator.minBy(Integer::compareTo);
        BinaryOperator<Integer> maxOperator2 = BinaryOperator.maxBy(Integer::compareTo);
        System.out.println("最小值: " + numbers.stream().reduce(minOperator).orElse(0));
        System.out.println("最大值: " + numbers.stream().reduce(maxOperator2).orElse(0));
    }

    /**
     * 综合示例：使用多种函数式接口处理数据
     */
    @Test
    public void comprehensiveDemo() {
        // 创建用户数据
        List<User> users = Arrays.asList(
                new User("Alice", 25),
                new User("Bob", 30),
                new User("Charlie", 35),
                new User("David", 20),
                new User("Eve", 28)
        );

        // 使用Function提取用户名
        Function<User, String> nameExtractor = user -> user.getName();
        
        // 使用Predicate过滤年龄大于25的用户
        Predicate<User> ageFilter = user -> user.getAge() > 25;
        
        // 使用Consumer打印用户信息
        Consumer<User> userPrinter = user -> System.out.println("用户: " + user.getName() + ", 年龄: " + user.getAge());
        
        // 使用Supplier提供默认用户
        Supplier<User> defaultUserSupplier = () -> new User("Default", 0);

        // 综合操作：过滤年龄大于25的用户，提取用户名，排序并打印
        List<String> filteredUserNames = users.stream()
                .filter(ageFilter)
                .map(nameExtractor)
                .sorted()
                .collect(Collectors.toList());
        
        System.out.println("年龄大于25的用户: " + filteredUserNames);

        // 使用orElseGet处理可能为空的Optional
        Optional<User> userOptional = users.stream()
                .filter(u -> u.getName().equals("NonExistent"))
                .findFirst();
        
        User resultUser = userOptional.orElseGet(defaultUserSupplier);
        System.out.println("找到的用户或默认用户: " + resultUser.getName());

        // 使用Consumer处理每个用户
        System.out.println("所有用户信息:");
        users.forEach(userPrinter);
    }

    // 内部类用于综合示例
    static class User {
        private String name;
        private int age;

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

        @Override
        public String toString() {
            return "User{name='" + name + "', age=" + age + "}";
        }
    }
}